package com.woniuxy.cloud.ticket.ticketgateway.filters;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniuxy.cloud.ticket.ticketgateway.JWTHelper;
import com.woniuxy.cloud.ticket52.common.result.Result;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.Charset;
import java.util.List;

@Component
@Slf4j
public class AuthFilter implements GlobalFilter {

    @Value("${auth.exclude-patterns}")
    private List<String> excludePatterns;

    @Autowired
    @Qualifier("jwtHelper")
    private JWTHelper jwtHelper;

    @Autowired
    @Qualifier("bossJwtHelper")
    private JWTHelper bossJwtHelper;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //判断是否是登录的路径，若是，放行
        String uri = exchange.getRequest().getPath().toString();
        log.info("uri:{}", uri);
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        for (String excludePattern : excludePatterns) {
            if(antPathMatcher.match(excludePattern, uri)){
                log.info("放行请求{}",uri);
                return chain.filter(exchange);
            }
        }


        //读取到jwt
        List<String> auth = exchange.getRequest().getHeaders().get("auth");

        if (!CollectionUtils.isEmpty(auth) && auth.get(0) != null) {
            if(uri.startsWith("/boss")){//boss请求
                try {
                    log.info("boss处理");

                    Claims payload = bossJwtHelper.parseJWT(auth.get(0));
                    log.info("payload{}",payload);
                    //从jwt的payload中获取信息并且设置到header中
                    Object operatorIdObj = payload.get("operatorId");
                    if (operatorIdObj != null) {
                        Integer operatorId = (Integer) operatorIdObj;
                        exchange.getRequest().mutate().header("operatorId", "" + operatorId);
                    }
                    Object operatorNameObj = payload.get("operatorName");
                    if (operatorNameObj != null) {
                        exchange.getRequest().mutate().header("operatorName", operatorNameObj.toString());
                    }
                    return chain.filter(exchange);
                }catch (Exception e){
                    log.warn("jwt解析异常",e);
                    return getVoidMono(exchange.getResponse());
                }

            }else {//前台
                try {
                    //解析jwt
                    //使用jwt工具和私钥解析
                    Claims claims = jwtHelper.parseJWT(auth.get(0));
                    if (claims.get("userId") != null) {
                        log.info("userId={}", claims.get("userId"));
                        Integer userId = (Integer) claims.get("userId");
                        // 如果成功，放行
                        exchange.getRequest().mutate().header("userId", "" + userId);
                    }
                    return chain.filter(exchange);
                } catch (JwtException e) {
                    log.warn("jwt解析异常",e);
                    // 如果失败，拒绝
                    return getVoidMono(exchange.getResponse());
                }
            }
        }
        return getVoidMono(exchange.getResponse());
    }

    @Autowired
    private ObjectMapper mapper;

    private Mono<Void> getVoidMono(ServerHttpResponse response) {
        Result result = Result.fail("请先登录");
        //解决乱码问题
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        try {
            //将结果转换为dataBuffer写出
            String resultJson = mapper.writeValueAsString(result);
            DataBuffer dataBuffer = response.bufferFactory().wrap(resultJson.getBytes(Charset.forName("utf-8")));
            return response.writeWith(Mono.just(dataBuffer));
        } catch (JsonProcessingException jpe) {
            throw new RuntimeException("JSON转换出错", jpe);
        }
    }
}

